<!DOCTYPE html>
<html>
  <head>
    <title>Test for slicing blobs that originated in a parent process</title>
    <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js">
    </script>
    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
  </head>
  <body onload="setup();">
    <script type="application/javascript;version=1.7">
"use strict";

function childFrameScript() {
  "use strict";

  const { classes: Cc, interfaces: Ci } = Components;

  const messageName = "test:blob-slice-test";
  const blobData = ["So", " ", "many", " ", "blobs!"];
  const blobText = blobData.join("");
  const blobType = "text/plain";

  const sliceText = "an";

  function info(msg) {
    sendAsyncMessage(messageName, { op: "info", msg: msg });
  }

  function ok(condition, name, diag) {
    sendAsyncMessage(messageName,
                     { op: "ok",
                       condition: condition,
                       name: name,
                       diag: diag });
  }

  function is(a, b, name) {
    let pass = a == b;
    let diag = pass ? "" : "got " + a + ", expected " + b;
    ok(pass, name, diag);
  }

  function finish(result) {
    sendAsyncMessage(messageName, { op: "done", result: result });
  }

  function grabAndContinue(arg) {
    testGenerator.send(arg);
  }

  function testSteps() {
    addMessageListener(messageName, grabAndContinue);
    let message = yield undefined;

    let blob = message.data;

    ok(blob instanceof Ci.nsIDOMBlob, "Received a Blob");
    is(blob.size, blobText.length, "Blob has correct length");
    is(blob.type, blobType, "Blob has correct type");

    info("Reading blob");

    let reader = new FileReader();
    reader.addEventListener("load", grabAndContinue);
    reader.readAsText(blob);

    yield undefined;

    is(reader.result, blobText, "Blob has correct data");

    let firstSliceStart = blobData[0].length + blobData[1].length;
    let firstSliceEnd = firstSliceStart + blobData[2].length;

    let slice = blob.slice(firstSliceStart, firstSliceEnd, blobType);

    ok(slice instanceof Ci.nsIDOMBlob, "Slice returned a Blob");
    is(slice.size, blobData[2].length, "Slice has correct length");
    is(slice.type, blobType, "Slice has correct type");

    info("Reading slice");

    reader = new FileReader();
    reader.addEventListener("load", grabAndContinue);
    reader.readAsText(slice);

    yield undefined;

    is(reader.result, blobData[2], "Slice has correct data");

    let secondSliceStart = blobData[2].indexOf("a");
    let secondSliceEnd = secondSliceStart + sliceText.length;

    slice = slice.slice(secondSliceStart, secondSliceEnd, blobType);

    ok(slice instanceof Ci.nsIDOMBlob, "Second slice returned a Blob");
    is(slice.size, sliceText.length, "Second slice has correct length");
    is(slice.type, blobType, "Second slice has correct type");

    info("Sending second slice");
    finish(slice);

    yield undefined;
  }

  let testGenerator = testSteps();
  testGenerator.next();
}

function parentFrameScript(mm) {
  const messageName = "test:blob-slice-test";
  const blobData = ["So", " ", "many", " ", "blobs!"];
  const blobText = blobData.join("");
  const blobType = "text/plain";

  const sliceText = "an";

  function grabAndContinue(arg) {
    testGenerator.send(arg);
  }

  function testSteps() {
    let slice = yield undefined;

    ok(slice instanceof Blob, "Received a Blob");
    is(slice.size, sliceText.length, "Slice has correct size");
    is(slice.type, blobType, "Slice has correct type");

    let reader = new FileReader();
    reader.onload = grabAndContinue;
    reader.readAsText(slice);
    yield undefined;

    is(reader.result, sliceText, "Slice has correct data");
    SimpleTest.finish();

    yield undefined;
  }

  let testGenerator = testSteps();
  testGenerator.next();

  mm.addMessageListener(messageName, function(message) {
    let data = message.data;
    switch (data.op) {
      case "info": {
        info(data.msg);
        break;
      }

      case "ok": {
        ok(data.condition, data.name, data.diag);
        break;
      }

      case "done": {
        testGenerator.send(data.result);
        break;
      }

      default: {
        ok(false, "Unknown op: " + data.op);
        SimpleTest.finish();
      }
    }
  });

  mm.loadFrameScript("data:,(" + childFrameScript.toString() + ")();",
                      false);

  let blob = new Blob(blobData, { type: blobType });
  mm.sendAsyncMessage(messageName, blob);
}

function setup() {
  info("Got load event");

  SpecialPowers.pushPrefEnv(
    { set: [ ["dom.ipc.browser_frames.oop_by_default", true],
             ["dom.mozBrowserFramesEnabled", true],
             ["network.disable.ipc.security", true],
             ["browser.pagethumbnails.capturing_disabled", true] ] },
    function() {
      info("Prefs set");

      SpecialPowers.pushPermissions(
        [ { type: "browser", allow: true, context: document } ],
        function() {
          info("Permissions set");

          let iframe = document.createElement("iframe");
          SpecialPowers.wrap(iframe).mozbrowser = true;
          iframe.id = "iframe";
          iframe.src =
            "data:text/html,<!DOCTYPE HTML><html><body></body></html>";

          iframe.addEventListener("mozbrowserloadend", function() {
            info("Starting tests");

            let mm = SpecialPowers.getBrowserFrameMessageManager(iframe)
            parentFrameScript(mm);
          });

          document.body.appendChild(iframe);
        }
      );
    }
  );
}

SimpleTest.waitForExplicitFinish();
    </script>
  </body>
</html>
